﻿using System.ComponentModel;
using System.Windows;
using System.Windows.Media.Media3D;
using System.Windows.Input;

namespace WpfHeadtracking
{
    /// <summary>
    /// Implements the Mouse Cursor as Headtracking Provider.
    /// </summary>
    public class MouseHeadtrackingProvider : DependencyObject, IHeadtrackingProvider
    {
        #region Fields

        private bool isHeadtracking;
        private Point3D headPosition = new Point3D(0, 0, 0);

        #endregion

        public FrameworkElement TrackingArea
        {
            get { return (FrameworkElement)GetValue(TrackingAreaProperty); }
            set { SetValue(TrackingAreaProperty, value); }
        }

        public static readonly DependencyProperty TrackingAreaProperty =
            DependencyProperty.Register("TrackingArea", typeof(FrameworkElement), typeof(MouseHeadtrackingProvider), new UIPropertyMetadata(null));

        #region IHeadtrackingProvider Members

        public Point3D HeadPosition
        {
            get { return headPosition; }
        }

        public bool IsHeadtracking
        {
            get { return isHeadtracking; }
        }

        public void SetHeadOrigin()
        {
            // does nothing. The origin is always the center of Element.
        }

        public void StartHeadtracking()
        {
            TrackingArea.MouseMove += TrackingArea_MouseMove;
            TrackingArea.MouseLeave += TrackingArea_MouseLeave;
            TrackingArea.MouseWheel += TrackingArea_MouseWheel;
        }

        void TrackingArea_MouseWheel(object sender, MouseWheelEventArgs e)
        {
            headPosition.Z -= e.Delta * 0.001;
            OnHeadPositionChanged();
        }

        void TrackingArea_MouseLeave(object sender, MouseEventArgs e)
        {
            isHeadtracking = false;
        }

        void TrackingArea_MouseMove(object sender, MouseEventArgs e)
        {
            if (TrackingArea.ActualWidth * TrackingArea.ActualHeight == 0)
            {
                isHeadtracking = false;
                return;
            }
            headPosition.X = ((e.GetPosition(TrackingArea).X) / TrackingArea.ActualWidth - 0.5) * (TrackingArea.ActualWidth / TrackingArea.ActualHeight);
            headPosition.Y = (e.GetPosition(TrackingArea).Y) / TrackingArea.ActualHeight - 0.5;
            isHeadtracking = true;
            OnHeadPositionChanged();
        }

        public void StopHeadtracking()
        {
            isHeadtracking = false;
        }

        public event PropertyChangedEventHandler HeadPositionChanged;

        protected void OnHeadPositionChanged()
        {
            PropertyChangedEventHandler handler = HeadPositionChanged;
            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs("HeadPosition"));
            }
        }

        #endregion

    }
}